home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
wtek0693.zip
/
MULTIMED.ZIP
/
WAVEPLAY.C
next >
Wrap
C/C++ Source or Header
|
1993-03-21
|
20KB
|
617 lines
//*******************************************************************
// Program: WavePlay
//
// This program uses MCI to play wave files. It demonstrates opening
// wave elements independently of the waveform device, use of
// MCI_NOTIFY to determine that a wave element has completed
// playback, and WM_ACTIVATE processing. The waveform device is
// opened as shareable to allow other programs a chance to use it
// without having to close WavePlay's element and device instances.
// Notice that when WavePlay becomes inactive a playing element
// stops playback. When WavePlay becomes active, playback resumes
// from the point wher is stopped. Notice in the command menu that
// there is both a STOP and a PAUSE command. On the surface they
// appear to have the same function. The difference is that a
// PAUSE command will halt playback without affecting MCI_NOTIFY.
// STOP, in contrast, will cause an MCI_NOTIFY_ABORTED.
//*******************************************************************
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dir.h>
#include <commdlg.h>
#include <mmsystem.h>
#include "waveplay.h"
// data initialized by first instance
typedef
struct tagSETUPDATA
{
char szAppName[10]; // name of application
} SETUPDATA;
SETUPDATA SetUpData;
// Data that can be referenced throughout the
// program but not passed to other instances
HINSTANCE hInst; // hInstance of application
HWND hWndMain; // hWnd of main window
UINT wDeviceID = 0; // "waveaudio" device instance
UINT wElementID = 0; // wave element instance
DWORD dwMediaLength = 0L; // length of the wave element
DWORD dwTimeFormat = MCI_FORMAT_MILLISECONDS; // current time format
int cxChar,cyChar; // character size
// wave element name
char szFileTitle[128];
// function prototypes
int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,int cmdShow);
void InitWavePlay(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,int cmdShow);
LRESULT CALLBACK WavePlayWndProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam);
BOOL OpenDevice(HWND hWnd);
BOOL OpenElement(HWND hWnd,LPSTR szElementName);
BOOL Play(HWND hWnd);
BOOL SeekTo(HWND hWnd);
BOOL Status(HWND hWnd,DWORD dwStatusOption,DWORD dwStatusItem,DWORD *pdwStatusReturn);
BOOL Set(HWND hWnd,DWORD dwSetOption,DWORD dwSetItem);
BOOL CloseWave(HWND hWnd,UINT *wID);
BOOL Stop(HWND hWnd);
BOOL Pause(HWND hWnd);
BOOL Resume(HWND hWnd);
BOOL GenericMciCommand(HWND hWnd,UINT wMessage);
void HandleError(HWND hWnd,DWORD dwErrVal);
void WavePlayPaint(HWND hWnd);
void CloseWavePlay(HWND hWnd);
void SetupMenu(HMENU hMenu,UINT wEnableFlagPlay,UINT wEnableFlagStop,
UINT wEnableFlagPause,UINT wEnableFlagResume);
//*******************************************************************
// WinMain - WavePlay main
//
//*******************************************************************
int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,int cmdShow)
{
MSG msg;
InitWavePlay(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
//*******************************************************************
// InitWavePlay - Init the WavePlay application.
//
//*******************************************************************
#pragma argsused
void InitWavePlay(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,int cmdShow)
{
WNDCLASS wcWavePlayClass;
if (!hPrevInstance) // if no previous instance, this is first
{
// Get string from resource with application name.
LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
// Define the window class for this application.
wcWavePlayClass.lpszClassName = SetUpData.szAppName;
wcWavePlayClass.hInstance = hInstance;
wcWavePlayClass.lpfnWndProc = WavePlayWndProc;
wcWavePlayClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWavePlayClass.hIcon = LoadIcon(hInstance, SetUpData.szAppName);
wcWavePlayClass.lpszMenuName = (LPSTR) SetUpData.szAppName;
wcWavePlayClass.hbrBackground = GetStockObject(WHITE_BRUSH);
wcWavePlayClass.style = CS_HREDRAW | CS_VREDRAW;
wcWavePlayClass.cbClsExtra = 0;
wcWavePlayClass.cbWndExtra = 0;
// Register the class
RegisterClass(&wcWavePlayClass);
}
else
{
// get the results of the initialization of first instance
GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
}
hInst = hInstance; // save for use by window procs
// Create applications main window.
hWndMain = CreateWindow(
SetUpData.szAppName, // window class name
SetUpData.szAppName, // window title
WS_OVERLAPPEDWINDOW | // type of window
WS_HSCROLL |
WS_VSCROLL,
CW_USEDEFAULT, // x window location
0, // y
CW_USEDEFAULT, // cx and size
0, // cy
NULL, // no parent for this window
NULL, // use the class menu
hInstance, // who created this window
NULL); // no parms to pass on
// Update display of main window.
ShowWindow(hWndMain, cmdShow);
UpdateWindow(hWndMain);
}
//*******************************************************************
// WavePlayWndProc - Handles messages for this application.
//
//*******************************************************************
LRESULT CALLBACK WavePlayWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
OPENFILENAME ofn;
static char szFile[128];
static char szFilter[30] = "Wave Files (*.WAV)\0*.WAV\0";
static char szDirName[128];
static HMENU hMenu;
HDC hDC;
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
szFile[0] = '\0';
szFileTitle[0] = '\0';
// get text metrics for paint
hDC = GetDC(hWnd);
GetTextMetrics(hDC, &tm);
ReleaseDC(hWnd,hDC);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
hMenu = GetMenu(hWnd);
OpenDevice(hWnd);
return(DefWindowProc(hWnd, message, wParam, lParam));
case WM_COMMAND:
switch(wParam)
{
case IDM_QUIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_OPEN:
// Set up the common file open dialog
getcwd(szDirName,sizeof(szDirName));
memset(&ofn,0,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrFile= szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = sizeof(szFileTitle);
ofn.lpstrInitialDir = szDirName;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn))
{
if (wDeviceID)
{
if (OpenElement(hWnd,szFile))
{
// Set the device's time format
Set(hWnd,MCI_SET_TIME_FORMAT,dwTimeFormat);
// Retrieve the total element length
Status(hWnd,MCI_STATUS_ITEM,MCI_STATUS_LENGTH,&dwMediaLength);
SetupMenu(hMenu,MF_ENABLED,MF_GRAYED,MF_GRAYED,MF_GRAYED);
InvalidateRect(hWnd,NULL,TRUE);
UpdateWindow(hWnd);
}
}
}
break;
case IDM_PLAY:
// Play the element
if (Play(hWnd))
SetupMenu(hMenu,MF_GRAYED,MF_ENABLED,MF_ENABLED,MF_GRAYED);
break;
case IDM_STOP:
// Halt playback - causes MCI_NOTIFYABORTED
if (Stop(hWnd))
SetupMenu(hMenu,MF_ENABLED,MF_GRAYED,MF_GRAYED,MF_GRAYED);
break;
case IDM_PAUSE:
// Pause playback
if (Pause(hWnd))
SetupMenu(hMenu,MF_GRAYED,MF_GRAYED,MF_GRAYED,MF_ENABLED);
break;
case IDM_RESUME:
// Resume PAUSEd playback
if (Resume(hWnd))
SetupMenu(hMenu,MF_GRAYED,MF_ENABLED,MF_ENABLED,MF_GRAYED);
break;
default:
break;
}
break;
case MM_MCINOTIFY:
// Processed for MCI_PLAY
switch(wParam)
{
case MCI_NOTIFY_SUCCESSFUL:
// Playback done - go back to start
if (SeekTo(hWnd))
SetupMenu(hMenu,MF_ENABLED,MF_GRAYED,MF_GRAYED,MF_GRAYED);
else
SetupMenu(hMenu,MF_GRAYED,MF_GRAYED,MF_GRAYED,MF_GRAYED);
break;
case MCI_NOTIFY_SUPERSEDED:
break;
case MCI_NOTIFY_ABORTED:
break;
case MCI_NOTIFY_FAILURE:
break;
default:
break;
}
break;
case WM_PAINT:
// Go paint the client area of the window
WavePlayPaint(hWnd);
break;
case WM_ACTIVATE:
if (wParam == WA_INACTIVE)
{
// Save the time format in case it gets changed then stop playback
if (wElementID)
{
Status(hWnd,MCI_STATUS_ITEM,MCI_STATUS_TIME_FORMAT,&dwTimeFormat);
Stop(hWnd);
}
}
else
{
// Restore the time format and continue playing
if (wElementID)
{
Set(hWnd,MCI_SET_TIME_FORMAT,dwTimeFormat);
Play(hWnd);
}
}
break;
case WM_DESTROY:
// This is the end if we were closed by a DestroyWindow call.
CloseWavePlay(hWnd); // take any necessary wrapup action.
PostQuitMessage(0); // this is the end...
break;
case WM_QUERYENDSESSION:
// If we return TRUE we are saying it's ok with us to end the
// windows session.
CloseWavePlay(hWnd); // take any necessary wrapup action.
return((long)TRUE); // we agree to end session.
case WM_CLOSE:
// Tell windows to destroy our window.
DestroyWindow(hWnd);
break;
default:
// Let windows handle all messages we choose to ignore.
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return(0L);
}
//*******************************************************************
// OpenDevice - Open only the device and initialize the device
// instance.
//
//*******************************************************************
BOOL OpenDevice(HWND hWnd)
{
DWORD dwRetVal;
MCI_WAVE_OPEN_PARMS mciOpenParms;
memset(&mciOpenParms,0,sizeof(mciOpenParms));
mciOpenParms.lpstrDeviceType = "waveaudio";
dwRetVal = mciSendCommand(wDeviceID,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_SHAREABLE|MCI_WAIT,(DWORD)(LPVOID)&mciOpenParms);
if (!dwRetVal)
{
wDeviceID = mciOpenParms.wDeviceID;
return TRUE;
}
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// OpenElement - Open the device element and initialize the element
// instance. Notice that wDeviceID is passed in as the ID to the
// MCI_OPEN command.
//
//*******************************************************************
BOOL OpenElement(HWND hWnd,LPSTR szElementName)
{
DWORD dwRetVal;
MCI_WAVE_OPEN_PARMS mciOpenParms;
if (wElementID)
{
if (CloseWave(hWnd,&wElementID))
wElementID = 0;
}
memset(&mciOpenParms,0,sizeof(mciOpenParms));
mciOpenParms.lpstrElementName = szElementName;
dwRetVal = mciSendCommand(wDeviceID,MCI_OPEN,MCI_OPEN_ELEMENT|MCI_WAIT,(DWORD)(LPVOID)&mciOpenParms);
if (!dwRetVal)
{
wElementID = mciOpenParms.wDeviceID;
return TRUE;
}
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// Play - Calls MCI_PLAY to begin element playback. Notice that
// MCI_NOTIFY is specified. When playbach is done a MCI_NOTIFY
// message will be sent to hWnd's proc.
//
//*******************************************************************
BOOL Play(HWND hWnd)
{
DWORD dwRetVal;
MCI_PLAY_PARMS mciPlayParms;
memset(&mciPlayParms,0,sizeof(mciPlayParms));
mciPlayParms.dwCallback = (DWORD)hWnd;
dwRetVal = mciSendCommand(wElementID,MCI_PLAY,MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);
if (!dwRetVal)
return TRUE;
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// SeekTo - Calls MCI_SEEK to seek to the start of an element.
//
//*******************************************************************
BOOL SeekTo(HWND hWnd)
{
DWORD dwRetVal;
MCI_SEEK_PARMS mciSeekParms;
memset(&mciSeekParms,0,sizeof(mciSeekParms));
dwRetVal = mciSendCommand(wElementID,MCI_SEEK,MCI_SEEK_TO_START | MCI_WAIT,
(DWORD)(LPVOID)&mciSeekParms);
if (!dwRetVal)
return TRUE;
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// Status - Calls MCI_STATUS to retrieve information about the
// state of the element.
//
//*******************************************************************
BOOL Status(HWND hWnd,DWORD dwStatusOption,DWORD dwStatusItem,DWORD *pdwStatusReturn)
{
DWORD dwRetVal;
MCI_STATUS_PARMS mciStatusParms;
memset(&mciStatusParms,0,sizeof(mciStatusParms));
mciStatusParms.dwItem = dwStatusItem;
dwRetVal = mciSendCommand(wElementID,MCI_STATUS,dwStatusOption | MCI_WAIT,(DWORD)(LPVOID)&mciStatusParms);
if (!dwRetVal)
{
*pdwStatusReturn = mciStatusParms.dwReturn;
return TRUE;
}
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// Set - Calls MCI_SET to change the state of the element.
//
//*******************************************************************
BOOL Set(HWND hWnd,DWORD dwSetOption,DWORD dwSetItem)
{
DWORD dwRetVal;
MCI_SET_PARMS mciSetParms;
memset(&mciSetParms,0,sizeof(mciSetParms));
mciSetParms.dwTimeFormat = dwSetItem;
dwRetVal = mciSendCommand(wElementID,MCI_SET,dwSetOption | MCI_WAIT,(DWORD)(LPVOID)&mciSetParms);
if (!dwRetVal)
{
return TRUE;
}
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// CloseWave - Calls MCI_CLOSE to close the instance specified by
// wID. If successful, sets wID to 0.
//
//*******************************************************************
BOOL CloseWave(HWND hWnd,UINT *wID)
{
DWORD dwRetVal;
MCI_GENERIC_PARMS mciGenericParms;
memset(&mciGenericParms,0,sizeof(mciGenericParms));
dwRetVal = mciSendCommand(*wID,MCI_CLOSE,MCI_WAIT,(DWORD)(LPVOID)&mciGenericParms);
if (!dwRetVal)
{
*wID = 0;
return TRUE;
}
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// Stop - Calls MCI_STOP to halt element playback. This will cause an
// MCI_NOTIFY_ABORTED to be sent to hWnd's proc.
//
//*******************************************************************
BOOL Stop(HWND hWnd)
{
return GenericMciCommand(hWnd,MCI_STOP);
}
//*******************************************************************
// Pause - Calls MCI_PAUSE to halt element playback. Has no effect
// on the MCI_NOTIFY notification status.
//
//*******************************************************************
BOOL Pause(HWND hWnd)
{
return GenericMciCommand(hWnd,MCI_PAUSE);
}
//*******************************************************************
// Resume - Calls MCI_RESUME to start playback of a paused element.
//
//*******************************************************************
BOOL Resume(HWND hWnd)
{
return GenericMciCommand(hWnd,MCI_RESUME);
}
//*******************************************************************
// GenericMciCommand - Some commands do not have their own parameter
// blocks. For these it is enough to specify the command.
//
//*******************************************************************
BOOL GenericMciCommand(HWND hWnd,UINT wMessage)
{
DWORD dwRetVal;
MCI_GENERIC_PARMS mciGenericParms;
memset(&mciGenericParms,0,sizeof(mciGenericParms));
dwRetVal = mciSendCommand(wElementID,wMessage,MCI_WAIT,(DWORD)(LPVOID)&mciGenericParms);
if (!dwRetVal)
return TRUE;
else
{
HandleError(hWnd,dwRetVal);
return FALSE;
}
}
//*******************************************************************
// HandleError - Calls mciGetErrorString to process an error
// condition. Displays the error in a MessageBox.
//
//*******************************************************************
void HandleError(HWND hWnd,DWORD dwErrVal)
{
char szErrorString[128];
if (!mciGetErrorString(dwErrVal,szErrorString,sizeof(szErrorString)))
strcpy(szErrorString,"mciGetErrorString Failed!");
MessageBox(hWnd,szErrorString,NULL,MB_OK | MB_ICONSTOP);
}
//*******************************************************************
// WavePlayPaint - paint the main window
//*******************************************************************
void WavePlayPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hDC;
char buffer[30];
hDC = BeginPaint(hWnd,&ps);
sprintf(buffer,"Element Name: %s",szFileTitle);
TextOut(hDC,cxChar,cyChar,buffer,strlen(buffer));
sprintf(buffer,"Media Length: %ld Milliseconds",dwMediaLength);
TextOut(hDC,cxChar,cyChar * 3,buffer,strlen(buffer));
EndPaint(hWnd,&ps);
}
//*******************************************************************
// CloseWavePlay - Done at termination of every instance of WavePlay.
// Closes the device and element.
//*******************************************************************
void CloseWavePlay(HWND hWnd)
{
if (wElementID)
CloseWave(hWnd,&wElementID);
if (wElementID)
CloseWave(hWnd,&wDeviceID);
}
//*******************************************************************
// SetupMenu - toggles the enable of the Command menu entries.
//*******************************************************************
void SetupMenu(HMENU hMenu,UINT wEnableFlagPlay,UINT wEnableFlagStop,
UINT wEnableFlagPause,UINT wEnableFlagResume)
{
EnableMenuItem(hMenu,IDM_PLAY,wEnableFlagPlay);
EnableMenuItem(hMenu,IDM_STOP,wEnableFlagStop);
EnableMenuItem(hMenu,IDM_PAUSE,wEnableFlagPause);
EnableMenuItem(hMenu,IDM_RESUME,wEnableFlagResume);
}
//*******************************************************************